模拟赛题解/2025.9.25 模拟赛
T1-微光(glow)
题面
你设计了一种新的屏保——也是一些彩色的泡泡。为了简化模型,你决定从一维上的问题下手:你现在有一根长为 米的线段,在上面有 个泡泡,每个泡泡以 米/秒的速度,匀速沿着线段,在两个可能方向中的一个方向上移动,并以可能的 种颜色中的其中一种着色。
你设定:如果一个泡泡和另一个泡泡相碰,则该泡泡会改变方向,向着相反的方向以相同速度继续运动。此外,向左运动的颜色为 的泡泡和向右运动颜色为 的泡泡发生碰撞后,先前向左的泡泡的颜色会变成 ,而先前向右的泡泡颜色变为 。
给你所有泡泡的初始位置、颜色、运动方向,对于每种颜色,确定所有泡泡以该种颜色着色在离开线段前运动的总行程。
。
题解
改变方向太麻烦了,考虑不改变点的移动方向。
问题就转化成两个点相遇后继续向前,其中向右的点颜色不变,向左的点改为二者颜色之和。
于是向右的点的总权值是容易统计的。
向左的点可以考虑模拟这个过程,但是基于点模拟太慢了,可以基于颜色模拟,记忆每种颜色有几个点。
遇到向左的点就加入,向右的点就更改,因为 相当小所以可以暴力修改。
于是直接得到一个 的暴力做法。
T2-泪雨(namidame)
题面
给定小写英文字母和 ? 组成的字符串 。
“泪雨” 定义为这样的串:这是一个回文串,并且 ? 的个数大于等于小写英文字符的个数。
请对于是 “泪雨” 的 的所有子串,求出它们问号位置的和之和。(位置下标从 开始)
形式化题意:定义:
请你求 ,其中 。
。
题解
先找出回文串然后考虑如何算贡献。
对于一个符合泪雨性质的子串,我们注意到因为它是一个回文串,所以其问号的位置之和即为问号数量乘以其中心位置。
而 维护的就是对于一个点,以其为中心的最大回文串长度。
所以可以考虑在 过程中维护以该点为中心的所有“泪雨”串的问号数量之和。
对于一个点,我们可以跟 一样从其对称点进行转移。
考虑到可能出现超出当前右边界的情况,我们注意到可以直接向内减小字符串,于是暴力收缩。
这样的复杂度其实是正确的。记回文半径为 ,从 处转移,我们考虑当前最右的区间 ,我们在 时就更新回文区间和对应中心。当 时发生收缩,总的收缩长度:
如果发生了收缩, 就会变成 ,所以 ,复杂度是对的。
复杂度均摊 。
T3-深海(sort)
题面
小葱很好奇一个序列冒泡排序 轮之后的样子,具体地说,对于一个长度为 的排列 ,她有两种询问:
1 给定 ,求将 的区间 冒泡排序 轮之后, 这个数在数组中的下标。 2 给定 ,求将 的区间 冒泡排序 轮之后, 的值。
定义对 的区间 进行一轮冒泡排序为:依次对 操作,若 则交换 。
注意询问中的排序操作并不实际在 上生效,也就是说询问之间互相独立。小葱不会为难你,所以对于单个测试点,所有询问都是同一种。
。
题解
O=2
研究排序问题时(尤其是排列),可以先进行值域压缩:通常我们会把序列变成 - 序列,比较特殊的时候还会有压缩成 或其它更大一点值域的需求,在此不展开。
我们二分值域,随后把序列变成 ,接下来只需要判定询问的位置是 还是 。
考虑刻画一下冒泡排序的操作。对于下标从 到 的序列:
现在 之间没有区别,我们完全可以让最左边的那个 不断交换到最后,也相当于把最左边的 之后的下标减 再把它的下标设成 。注意一些边界,那么判定就是很简单的:
- 如果 序列中 的个数,那么显然序列已经排序完了。(不用特别划这个)
- 如果 ,那就说明出时它在长度为 的后缀上,只需要判断 的数量是否足够。
- 其余情况,我们只用数一下 前面有多少个 ,若只有 ,则答案显然就是 ;否则,答案就是绕过了长轮子移后到达 位置:。
对于区间询问,进行主席树上二分即可做到 。
O=1
由于涉及了具体的位置,我们不妨把值域压缩成 再观察(其实可以脱离值域压缩观察,因为只涉及和 比大小)。我们考虑 的动作。
首先,当前面有1时,和 一样,它的行为和 一致,每次会向前移动一步;当前面没有1的时候,它向后冒泡,直到遇见一个1,之后这个1就会向后冒泡。
同样地,考虑形式化这个东西:
- 如果 序列中 的个数,那么显然序列已经排序完了。
- 先统计现在 的位置前有多少个1,记为 的情况是平凡的,现在还要向后移动 次,代表我们要找到从左到右数的第 个1的位置,计算答案直接做。
- 否则较复杂,换句话考虑,考虑后面有多少个1会移到它前面,就是要知道的是从 的位置到 ,这样就做完了。
这一部分可以离线后扫扫描线,主席树即可。
时间复杂度 。
T4-虚无(nihility)
题面
你正在玩一种智力游戏,你需要让在迷宫起点处的棋子到达终点。
坐拥上帝视角的你已经知道了迷宫的全貌,这是一个 个点 条边的有向图,每条边有一个颜色 ,一个点连出的边颜色都不相同,且图中所有边的颜色只有 种。为了方便,我们把起点标号为 ,而终点为 。
这个游戏的流程是这样的:你有一个牌堆,在游戏最开始的时候,你可以向牌堆里加入任意多的牌,每张牌有颜色,颜色由你决定(在 中)。随后游戏开始:
假设当前棋子处在点 ,当前牌堆顶的牌颜色为 :
1 如果 向某个点 连了一条颜色为 的边,就把棋子向点 移动,并丢弃牌堆顶的这张牌。 2 否则,若牌堆为空或者不存在一条出边颜色为 ,你可以把棋子沿着该点任意一条出边移动。如果选择了一条颜色为 的边,则会在牌堆顶加入一张颜色为 的卡牌。
为了让游戏有挑战性,你想要让初始牌堆的牌数目尽可能少。你只需要求出这个最少的数目。
,对于输入的每条边 ,保证 。
题解
如果可达,那么答案必然 ,考虑在起点前加一些“没有限制”的虚点,以此使得可以在起点 获得所有可能方案,我们这样连边:
- 对于 号点,向 连所有颜色的边。
- 对于 向 连所有颜色的边。
没有限制的意思就是说:这些边只负责加牌,而不执行操作 。
这样如果我们能够从虚点 以空栈状态到达 ,答案就是 (若从 能到答案就是 )。
现在问题转化成了一个可达性问题,我们只需要判定是否空栈地从起点,以空栈的状态到达终点。
注意空栈任选走边加牌到非空栈时强制走边这个过程比较特殊,我们需要在状态里加入这个信息。
记 表示,存在一条路径使得空栈状态的 可以到达空栈状态 ,且,路径中不存在在一个空栈的时候有颜色为 的出边。转移考虑类似括号序列生成的转移。
第一种转移形似传递闭包,也可看作把两个括号序列拼在一起:
第二种转移仅在括号序列两侧加一对括号:如果 有一条颜色为 的入边 , 有一条颜色为 的出边 ,且 不存在一条颜色为 的出边, 。
注意此类转移对我们建的虚点也生效,因为它们没有要强制定之类的限制,也就是 时也执行转移。
注意一种情况:当前可能用满所有颜色边的时候(其实就是 连出了所有颜色的边的时候),我们新建一个颜色 ,即用解作这种情况。
转移顺序比较复杂,使用记忆化搜索即可。时间复杂度 。
